package com.sunny.framework.core.base.dao;

import java.io.Serializable;
import java.util.List;

import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;

public class BaseDao<T, ID extends Serializable> extends
		HibernateSessionFactory {

	@SuppressWarnings("unchecked")
	protected Class<T> persistentClass = (Class<T>) DAOUtil.getTypeArguments(
			BaseDao.class, this.getClass()).get(0);
	private DetachedCriteria detachedcriteria;

	/**
	 * get entity by id
	 * 
	 * @param id
	 */
	public T getObject(Serializable id) {
		detachedcriteria = DetachedCriteria.forClass(persistentClass);
		return this.getHibernateTemplate().get(persistentClass, id);
	}

	/**
	 * get the custom condition list number
	 * 
	 * @param detachedcriteria
	 * @return
	 */
	public Integer num(List<Criterion> criterions) {
		detachedcriteria = DetachedCriteria.forClass(persistentClass);
		for (Criterion criterion : criterions) {
			detachedcriteria.add(criterion);
		}
		detachedcriteria.setProjection(Projections.count("id"));
		@SuppressWarnings("unchecked")
		List<Object> objects = this.getHibernateTemplate().findByCriteria(
				detachedcriteria);
		return Integer.parseInt(objects.get(0).toString());
	}

	/**
	 * get the custom condition list
	 * 
	 * @param detachedcriteria
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<T> getList(List<Criterion> criterions) {
		detachedcriteria = DetachedCriteria.forClass(persistentClass);
		for (Criterion criterion : criterions) {
			detachedcriteria.add(criterion);
		}
		return this.getHibernateTemplate().findByCriteria(detachedcriteria);
	}

	@SuppressWarnings("unchecked")
	public List<T> getPageList(List<Criterion> criterions, Integer firstResult,
			Integer maxResults, List<Projection> projections, List<Order> orders) {
		detachedcriteria = DetachedCriteria.forClass(persistentClass);
		for (Criterion criterion : criterions) {
			detachedcriteria.add(criterion);
		}
		for (Projection projection : projections) {
			detachedcriteria.setProjection(projection);
		}
		for (Order order : orders) {
			detachedcriteria.addOrder(order);
		}
		return this.getHibernateTemplate().findByCriteria(detachedcriteria,
				firstResult, maxResults);
	}

	@SuppressWarnings("unchecked")
	public List<T> getPageList(List<Criterion> criterions, Integer firstResult,
			Integer maxResults, List<Order> orders) {
		detachedcriteria = DetachedCriteria.forClass(persistentClass);
		for (Criterion criterion : criterions) {
			detachedcriteria.add(criterion);
		}
		for (Order order : orders) {
			detachedcriteria.addOrder(order);
		}
		return this.getHibernateTemplate().findByCriteria(detachedcriteria,
				firstResult, maxResults);
	}

	@SuppressWarnings("unchecked")
	public List<T> getPageList(List<Criterion> criterions, Integer firstResult,
			Integer maxResults) {
		detachedcriteria = DetachedCriteria.forClass(persistentClass);
		for (Criterion criterion : criterions) {
			detachedcriteria.add(criterion);
		}
		return this.getHibernateTemplate().findByCriteria(detachedcriteria,
				firstResult, maxResults);
	}

	/**
	 * saveOrUpdate entity
	 * 
	 * @param t
	 */
	public void save(T t) {
		this.getHibernateTemplate().saveOrUpdate(t);
	}

	/**
	 * saveOrUpdate a lot of entity
	 * 
	 * @param ts
	 */
	public void saves(T... ts) {
		for (T t : ts) {
			save(t);
		}
	}

	/**
	 * delete entity delete
	 * 
	 * @param t
	 */
	public void delete(T t) {
		this.getHibernateTemplate().delete(t);
	}

	/**
	 * delete a lot of entity
	 * 
	 * @param ts
	 */
	public void delete(T... ts) {
		for (T t : ts) {
			delete(t);
		}
	}

	/**
	 * delete entity by id
	 * 
	 * @param id
	 */
	public void deleteById(Serializable id) {
		this.getHibernateTemplate().delete(getObject(id));
	}

	/**
	 * delete a lot of entity by id
	 * 
	 * @param ids
	 */
	public void deleteByIds(Serializable... ids) {
		for (Serializable serializable : ids) {
			deleteById(serializable);
		}
	}
}
